package com.uduemc.biso.node.web.api.service.impl;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysLanguage;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.node.core.common.dto.FeignCopyPage;
import com.uduemc.biso.node.core.common.entities.PageSystem;
import com.uduemc.biso.node.core.common.entities.SSL;
import com.uduemc.biso.node.core.common.feign.CCopyFeign;
import com.uduemc.biso.node.core.common.feign.CPageFeign;
import com.uduemc.biso.node.core.common.utils.PageUtil;
import com.uduemc.biso.node.core.dto.FeignFindInfosByHostSiteAndSystemTypeIds;
import com.uduemc.biso.node.core.entities.*;
import com.uduemc.biso.node.core.entities.custom.Download;
import com.uduemc.biso.node.core.feign.SPageFeign;
import com.uduemc.biso.node.core.utils.AssetsRepertoryUtil;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.core.utils.SiteUrlUtil;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.dto.RequestSPage;
import com.uduemc.biso.node.web.api.dto.RequestSPageCopy;
import com.uduemc.biso.node.web.api.exception.HostSetuptException;
import com.uduemc.biso.node.web.api.service.*;
import com.uduemc.biso.node.web.api.validator.currentsite.impl.CurrentSiteSPageRewriteExistValid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;

@Service
public class PageServiceImpl implements PageService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    // 默认对page 的排序
    public static String DEFAULT_ORDER_BY_CLAUSE = "`parent_id` ASC, `order_num` ASC, `id` ASC";

    @Resource
    private SPageFeign sPageFeign;

    @Resource
    private RequestHolder requestHolder;

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private CPageFeign cPageFeign;

    @Resource
    private CCopyFeign cCopyFeign;

    @Resource
    private SiteService siteServiceImpl;

    @Resource
    private LanguageService languageServiceImpl;

    @Resource
    private ArticleService articleServiceImpl;

    @Resource
    private ProductService productServiceImpl;

    @Resource
    private DownloadService downloadServiceImpl;

    @Resource
    private HostService hostServiceImpl;

    @Resource
    private DomainService domainServiceImpl;

    @Resource
    private SystemItemCustomLinkService systemItemCustomLinkServiceImpl;

    @Resource
    private SystemService systemServiceImpl;

    @Resource
    private WebSiteService webSiteServiceImpl;

    @Resource
    private HostSetupService hostSetupServiceImpl;

    @Override
    public SPage getBootPage() throws IOException {
        return getBootPage(requestHolder.getHost().getId());
    }

    @Override
    synchronized public SPage getBootPage(Long hostId) throws IOException {
        Long siteId = 0L;
        List<SPage> list = getInfosByHostSiteId(hostId, siteId);
        SPage bootPage = null;
        if (CollectionUtils.isEmpty(list)) {
            SPage extities = new SPage().setHostId(hostId).setSiteId(0L).setParentId(0L).setSystemId(0L).setVipLevel((short) -1).setType((short) 0)
                    .setName("引导页面").setStatus((short) 0);
            RestResult insert = sPageFeign.insert(extities);
            logger.info("insert: " + insert);
            bootPage = RestResultUtil.data(insert, SPage.class);
        } else {
            bootPage = list.get(0);
            if (list.size() > 1) {
                for (int i = 1; i < list.size(); i++) {
                    if (!delete(list.get(i))) {
                        logger.error("PageServiceImpl 删除数据失败！");
                        throw new RuntimeException("删除数据失败！ list.get(i): " + list.get(i));
                    }
                }
            }
        }
        logger.info("bootPage: " + bootPage);
        if (bootPage == null || bootPage.getId() == null || bootPage.getId().longValue() < 1L) {
            logger.error("通过Feign插入数据失败！");
            throw new RuntimeException("通过Feign插入数据失败！");
        }
        return bootPage;
    }

    @Override
    public List<SPage> getInfosByHostSiteId() throws IOException {
        return getInfosByHostSiteId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId());
    }

    @Override
    public List<SPage> getInfosByHostSiteId(Long hostId, Long siteId) throws IOException {
        RestResult restResult = sPageFeign.findByHostSiteIdAndOrderBy(hostId, siteId, DEFAULT_ORDER_BY_CLAUSE);
        JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, SPage.class);
        @SuppressWarnings("unchecked")
        List<SPage> data = (List<SPage>) RestResultUtil.data(restResult, valueType);
        return data;
    }

    @Override
    public SPage updateSPageById(SPage sPage) throws IOException {
        List<SPage> arrayList = new ArrayList<SPage>();
        arrayList.add(sPage);
        List<SPage> updateSPageById = updateSPageById(arrayList);
        if (CollectionUtils.isEmpty(updateSPageById)) {
            return null;
        }
        return updateSPageById.get(0);
    }

    @Override
    public List<SPage> updateSPageById(List<SPage> sPageList) throws IOException {
        List<SPage> updateList = new ArrayList<>();
        for (SPage sPage : sPageList) {
            if (sPage.getType().shortValue() == (short) 3 || sPage.getType().shortValue() == (short) 4) {
                sPage.setRewrite(null);
            }
            updateList.add(sPage);
        }
        RestResult restResult = sPageFeign.updateList(updateList);
        JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, SPage.class);
        @SuppressWarnings("unchecked")
        List<SPage> data = (List<SPage>) RestResultUtil.data(restResult, valueType);
        return data;
    }

    @Override
    public SPage insertSPageAppendOrderNum(SPage sPage)
            throws IOException, HostSetuptException {
        if (sPage.getType().shortValue() == (short) 3 || sPage.getType().shortValue() == (short) 4) {
            sPage.setRewrite(null);
        }
        RestResult restResult = sPageFeign.insertAppendOrderNum(sPage);
        SPage data = RestResultUtil.data(restResult, SPage.class);
        return data;
    }

    @Override
    public boolean delete(SPage sPage) throws IOException {
        if (requestHolder.getHost().getId().longValue() != sPage.getHostId().longValue()) {
            return false;
        }
        RestResult delete = cPageFeign.delete(sPage.getHostId(), sPage.getSiteId(), sPage.getId());
        if (delete.getCode() == 200) {
            return true;
        }
        return false;
    }

    @Override
    public SPage getInfoById(long id) throws IOException {
        RestResult restResult = sPageFeign.findOne(id);
        return RestResultUtil.data(restResult, SPage.class);
    }

    @Override
    public SPage getInfoById(long id, long hostId) throws IOException {
        SPage sPage = getInfoById(id);
        if (sPage != null && sPage.getHostId() != null && sPage.getHostId().longValue() == hostId) {
            return sPage;
        }
        return null;
    }

    @Override
    public SPage getInfoById(long id, long hostId, long siteId) throws IOException {
        SPage sPage = getInfoById(id);
        if (sPage != null && sPage.getHostId() != null && sPage.getHostId().longValue() == hostId && sPage.getSiteId() != null
                && sPage.getSiteId().longValue() == siteId) {
            return sPage;
        }
        return null;
    }

    @Override
    public SPage getInfoByHostSiteIdAndRewrite(String rewrite) throws IOException {
        return getInfoByHostSiteIdAndRewrite(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), rewrite);
    }

    @Override
    public SPage getInfoByHostSiteIdAndRewrite(Long hostId, Long siteId, String rewrite)
            throws IOException {
        RestResult restResult = sPageFeign.findByHostSiteIdAndRewrite(hostId, siteId, rewrite);
        return RestResultUtil.data(restResult, SPage.class);
    }

    @Override
    public boolean changeStatusById(long id, short status) throws IOException {
        return changeStatusById(id, requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), status);
    }

    @Override
    public boolean changeStatusById(long id, Long hostId, Long siteId, short status)
            throws IOException {
        RestResult findOne = sPageFeign.findByIdHostSiteId(id, hostId, siteId);
        SPage sPage = RestResultUtil.data(findOne, SPage.class);
        if (sPage == null) {
            return false;
        }
        // 确认当前 hostId、siteId 的数据
        sPage.setStatus(status);
        RestResult updateById = sPageFeign.updateById(sPage);
        SPage data = RestResultUtil.data(updateById, SPage.class);
        return data.getId().longValue() == sPage.getId().longValue();
    }

    @Override
    public boolean changeHideById(long id, short hide) throws IOException {
        return changeHideById(id, requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), hide);
    }

    @Override
    public boolean changeHideById(long id, long hostId, long siteId, short hide) throws IOException {
        RestResult findOne = sPageFeign.findByIdHostSiteId(id, hostId, siteId);
        SPage sPage = RestResultUtil.data(findOne, SPage.class);
        if (sPage == null) {
            return false;
        }
        sPage.setHide(hide);
        RestResult updateById = sPageFeign.updateById(sPage);
        SPage data = RestResultUtil.data(updateById, SPage.class);
        return data.getId().longValue() == sPage.getId().longValue();
    }

    @Override
    public SPage getCurrentInfoById(long id) throws IOException {
        RestResult restResult = sPageFeign.findByIdHostSiteId(id, requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId());
        SPage sPage = RestResultUtil.data(restResult, SPage.class);
        return sPage;
    }

    @Override
    public boolean validRewrite(SPage sPage) throws IOException {
        Short type = sPage.getType();
        if (type == null || type.shortValue() == (short) 3 || type.shortValue() == (short) 4) {
            return true;
        }
        SSystemItemCustomLink sSystemItemCustomLink = systemItemCustomLinkServiceImpl.findOneByHostSiteIdAndPathFinal(sPage.getHostId(), sPage.getSiteId(),
                sPage.getRewrite());
        if (sSystemItemCustomLink != null) {
            return false;
        }
        return validRewrite(sPage.getId(), sPage.getRewrite());
    }

    @Override
    public boolean validRewrite(Long id, String rewrite) throws IOException {

        if (StringUtils.isEmpty(rewrite)) {
            return false;
        }

        SPage sPageRewrite = getInfoByHostSiteIdAndRewrite(rewrite);

        if (id == null || id.longValue() < 1L) {
            // 是新增
            if (sPageRewrite != null) {
                // 如果不为空则是表示存在，存在则直接返回false
                return false;
            }
        } else {
            // 是修改
            if (sPageRewrite != null && sPageRewrite.getId().longValue() != id.longValue()) {
                // 如果不为空，并且与sPage.getId()不相等则直接返回false
                return false;
            }
        }

        return true;
    }

    @Override
    public boolean hasChildren(Long parentId) throws IOException {
        RestResult totalByParentId = sPageFeign.totalByParentId(parentId);
        Integer data = RestResultUtil.data(totalByParentId, Integer.class);
        if (data == null) {
            data = 0;
        }
        return data > 0;
    }

    @Override
    public List<SPage> getInfosBySystemId(Long systemId) throws IOException {
        return getInfosBySystemId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), systemId);
    }

    @Override
    public List<SPage> getInfosBySystemId(Long hostId, Long siteId, Long systemId)
            throws IOException {
        if (systemId == null) {
            return null;
        }
        RestResult restResult = sPageFeign.findByHostSiteSystemIdOrderBy(hostId, siteId, systemId, DEFAULT_ORDER_BY_CLAUSE);
        JavaType valueType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, SPage.class);
        @SuppressWarnings("unchecked")
        List<SPage> data = (List<SPage>) RestResultUtil.data(restResult, valueType);
        return data;
    }

    @Override
    public SPage getSPageByPageUtil(long hostId, long siteId, PageUtil pageUtil) {
        return null;
    }

    @Override
    public List<PageSystem> getCurrentInfosWithPageByTypes(List<Long> typeos)
            throws IOException {
        FeignFindInfosByHostSiteAndSystemTypeIds feignFindInfosByHostSiteAndSystemTypeIds = new FeignFindInfosByHostSiteAndSystemTypeIds();
        feignFindInfosByHostSiteAndSystemTypeIds.setHostId(requestHolder.getHost().getId()).setSiteId(requestHolder.getCurrentSite().getId())
                .setSystemTypeIds(typeos);
        RestResult restResult = cPageFeign.findSystemPageByHostSiteIdAndSystemTypes(feignFindInfosByHostSiteAndSystemTypeIds);
        @SuppressWarnings("unchecked")
        List<PageSystem> data = (List<PageSystem>) RestResultUtil.data(restResult, new TypeReference<List<PageSystem>>() {
        });
        return data;
    }

    @Override
    public SPage getCurrentHomePageIfNotCreate() throws IOException, HostSetuptException {
        SPage sPage = getInfoByHostSiteIdAndRewrite("shouye");
        if (sPage != null) {
            return sPage;
        }
        List<SPage> listSPage = getInfosByHostSiteId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId());
        if (!CollectionUtils.isEmpty(listSPage)) {
            for (SPage eleSpage : listSPage) {
                Short type = eleSpage.getType();
                if (type != null && (type.shortValue() == (short) 1 || type.shortValue() == (short) 2)) {
                    return eleSpage;
                }
            }
        }
        // 添加 home 页面
        SPage insert = new SPage();
        insert.setHostId(requestHolder.getHost().getId()).setSiteId(requestHolder.getCurrentSite().getId()).setParentId(0L).setSystemId(0L)
                .setVipLevel((short) -1).setType((short) 1).setName("首页").setStatus((short) 1).setHide((short) 0).setRewrite("shouye").setUrl("")
                .setTarget("_self");
        SPage insertSPageAppendOrderNum = insertSPageAppendOrderNum(insert);
        return insertSPageAppendOrderNum;
    }

    @Override
    public String pageUrl(SPage sPage) throws IOException {
        String domain = requestHolder.getDefaultDomain().getDomainName();
        if (StrUtil.isBlank(domain)) {
            return null;
        }
        Site defaultSite = siteServiceImpl.getDefaultSite(sPage.getHostId());
        if (defaultSite == null) {
            return null;
        }
        SSL infoSSL = domainServiceImpl.infoSSL(requestHolder.getDefaultDomain().getHostId(), requestHolder.getDefaultDomain().getId());
        boolean ssl = infoSSL == null ? false : true;
        Host host = requestHolder.getHost();
        HConfig hConfig = hostServiceImpl.getCurrentHostConfig();
        if (defaultSite.getId().longValue() == sPage.getSiteId().longValue()) {
            return SiteUrlUtil.getPagePathBySysdomainAccess(domain, ssl, null, sPage, hConfig, host);
        }
        SysLanguage sysLanguage = languageServiceImpl.getLanguageBySite(sPage.getSiteId().longValue());
        String fullPath = SiteUrlUtil.getPagePathBySysdomainAccess(domain, ssl, sysLanguage.getLanNo(), sPage, hConfig, host);
        return fullPath;
    }

    @Override
    public String systemItemUrl(SSystem sSystem, SPage sPage, long itemId)
            throws IOException {
        if (sSystem == null || sPage == null || itemId < 1) {
            return null;
        }

        return systemItemUrl(sSystem, sPage, requestHolder.getDefaultDomain(), itemId);
    }

    @Override
    public String systemItemUrl(SSystem sSystem, SPage sPage, long domainId, long itemId)
            throws IOException {
        HDomain hDomain = domainServiceImpl.getCurrentInfoById(domainId);
        if (hDomain == null) {
            return null;
        }
        return systemItemUrl(sSystem, sPage, hDomain, itemId);
    }

    @Override
    public String systemItemUrl(SSystem sSystem, SPage sPage, HDomain hDomain, long itemId)
            throws IOException {
        if (sSystem == null || sPage == null || hDomain == null || itemId < 1) {
            return null;
        }

        String domain = hDomain.getDomainName();
        if (StrUtil.isBlank(domain)) {
            return null;
        }
        Site defaultSite = siteServiceImpl.getDefaultSite(sPage.getHostId());
        if (defaultSite == null) {
            return null;
        }

        SysLanguage sysLanguage = languageServiceImpl.getLanguageBySite(sPage.getSiteId().longValue());
        if (sysLanguage == null) {
            return null;
        }

        Host host = requestHolder.getHost();
        HConfig hConfig = hostServiceImpl.getCurrentHostConfig();

        Long systemId = sSystem.getId();
        Long systemTypeId = sSystem.getSystemTypeId();

        SSL infoSSL = domainServiceImpl.infoSSL(hDomain.getHostId(), hDomain.getId());
        boolean ssl = infoSSL == null ? false : true;

        if (systemTypeId == null || systemId == null) {
            return null;
        }

        SSystemItemCustomLink sSystemItemCustomLink = systemItemCustomLinkServiceImpl.findOkOneByHostSiteSystemItemId(sSystem.getHostId(), sSystem.getSiteId(),
                sSystem.getId(), itemId);

        if (systemTypeId.longValue() == 1L) {
            // 找到对应的 item 数据
            SArticle sArticle = articleServiceImpl.getCurrentInfoById(itemId);
            if (sArticle == null || sArticle.getSystemId() == null || sArticle.getSystemId().longValue() != systemId) {
                return null;
            }
            String path = SiteUrlUtil.getPath(sPage, sArticle);
            if (sSystemItemCustomLink != null) {
                path = SiteUrlUtil.getPath(sSystemItemCustomLink);
            }
            String fullPath = null;
            if (defaultSite.getId().longValue() == sPage.getSiteId().longValue()) {
                fullPath = SiteUrlUtil.getSitePath(hDomain, ssl, null, path, hConfig, host);
            } else {
                fullPath = SiteUrlUtil.getSitePath(hDomain, ssl, sysLanguage.getLanNo(), path, hConfig, host);
            }

            return fullPath;
        } else if (systemTypeId.longValue() == 3L) {
            SProduct sProduct = productServiceImpl.getCurrentSProductById(itemId);
            if (sProduct == null || sProduct.getSystemId() == null || sProduct.getSystemId().longValue() != systemId) {
                return null;
            }
            String path = SiteUrlUtil.getPath(sPage, sProduct);
            if (sSystemItemCustomLink != null) {
                path = SiteUrlUtil.getPath(sSystemItemCustomLink);
            }
            String fullPath = null;
            if (defaultSite.getId().longValue() == sPage.getSiteId().longValue()) {
                fullPath = SiteUrlUtil.getSitePath(hDomain, ssl, null, path, hConfig, host);
            } else {
                fullPath = SiteUrlUtil.getSitePath(hDomain, ssl, sysLanguage.getLanNo(), path, hConfig, host);
            }
            return fullPath;
        } else if (systemTypeId.longValue() == 5L) {
            Download download = downloadServiceImpl.getCurrentDownloadBySystemDownloadId(systemId, itemId);
            if (download == null || download.getFileRepertoryQuote() == null || download.getFileRepertoryQuote().getHRepertory() == null) {
                return null;
            }
            HRepertory hRepertory = download.getFileRepertoryQuote().getHRepertory();
            String downloadHref = AssetsRepertoryUtil.getDownloadHref(hRepertory);
            String fullPath = null;
            if (defaultSite.getId().longValue() == sPage.getSiteId().longValue()) {
                fullPath = SiteUrlUtil.getSitePath(hDomain, ssl, null, downloadHref, hConfig, host);
            } else {
                fullPath = SiteUrlUtil.getSitePath(hDomain, ssl, sysLanguage.getLanNo(), downloadHref, hConfig, host);
            }
            return fullPath;
        }

        return null;
    }

    @Override
    public JsonResult save(RequestSPage requestSPage) throws IOException {
        Long id = requestSPage.getId();
        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();

        if (id == null || id.longValue() < 1) {
            // 新增页面
            return saveInsert(requestSPage, hostId, siteId);
        } else {
            // 修改页面
            return saveUpdate(requestSPage, hostId, siteId);
        }

    }

    protected synchronized JsonResult saveUpdate(RequestSPage requestSPage, long hostId, long siteId) throws IOException {
        SPage paramSPage = requestSPage.makeSPage();

        Long id = paramSPage.getId();
        if (id == null || id.longValue() < 1) {
            return JsonResult.illegal();
        }

        SPage sPage = getInfoById(id, hostId, siteId);
        if (sPage == null) {
            return JsonResult.illegal();
        }

        Long parentId = paramSPage.getParentId();
        Long systemId = paramSPage.getSystemId();
        Short vipLevel = paramSPage.getVipLevel();
        Short type = paramSPage.getType();
        String name = paramSPage.getName();
        Short status = paramSPage.getStatus();
        Short hide = paramSPage.getHide();
        String rewrite = paramSPage.getRewrite();
        String url = paramSPage.getUrl();
        String target = paramSPage.getTarget();

        if (parentId != null) {
            if (parentId.longValue() > 0) {
                SPage parentSPage = getInfoById(parentId, hostId, siteId);
                if (parentSPage == null) {
                    return JsonResult.illegal();
                }
            }

            sPage.setParentId(parentId);
        }

        if (type != null) {
            sPage.setType(type);
            if (type.shortValue() == (short) 0) {
                // 引导页
            } else if (type.shortValue() == (short) 1) {
                // 普通页
                if (systemId != null && systemId.longValue() != 0) {
                    return JsonResult.illegal();
                }
                sPage.setSystemId(0L);
            } else if (type.shortValue() == (short) 2) {
                // 系统页
                if (systemId == null || systemId.longValue() < 1) {
                    return JsonResult.illegal();
                }
                // 验证系统是否存在
                SSystem sSystem = systemServiceImpl.getInfoById(systemId, hostId, siteId);
                if (sSystem == null) {
                    return JsonResult.illegal();
                }
                sPage.setSystemId(systemId);
            } else if (type.shortValue() == (short) 3) {
                // 外链页
                if (StrUtil.isBlank(url)) {
                    return JsonResult.illegal();
                }
                sPage.setUrl(url);
                sPage.setRewrite("");
            } else if (type.shortValue() == (short) 4) {
                // 内链页
            }
        }

        if (vipLevel != null) {
            sPage.setVipLevel(vipLevel);
        }

        if (name != null) {
            if (StrUtil.length(name) < 1) {
                return JsonResult.illegal();
            }
            sPage.setName(name);
        }

        if (status != null) {
            if (status.shortValue() < (short) 0 || status.shortValue() > (short) 1) {
                return JsonResult.illegal();
            }
            sPage.setStatus(status);
        }

        if (hide != null) {
            if (hide.shortValue() < (short) 0 || hide.shortValue() > (short) 1) {
                return JsonResult.illegal();
            }
            sPage.setHide(hide);
        }

        if (rewrite != null && type.shortValue() != (short) 3) {
            // 自定义链接 是否包含特殊字符
            String pattern = "([\u4e00-\u9fa5]|[a-zA-Z0-9])+";
            if (!Pattern.matches(pattern, rewrite)) {
                return JsonResult.messageError("非全部数字或带空格特殊符号！");
            }
            // 自定义链接系统中是否存在
            List<Map<String, String>> defaultRewrite = CurrentSiteSPageRewriteExistValid.defaultRewrite;
            for (Map<String, String> ptn : defaultRewrite) {
                if (CurrentSiteSPageRewriteExistValid.isMatch(ptn.get("pattern"), rewrite)) {
                    return JsonResult.messageError("自定义链接在系统中已存在！");
                }
            }
            sPage.setRewrite(rewrite);
            if (!validRewrite(sPage)) {
                return JsonResult.messageError("自定义链接系统中已存在");
            }
        }

        if (target != null && StrUtil.length(target) > 0) {
            sPage.setTarget(target);
        }

        SPage update = updateSPageById(sPage);

        if (update == null) {
            return JsonResult.assistance();
        }

        webSiteServiceImpl.cacheCurrentSiteClear();

        return JsonResult.messageSuccess(update);

    }

    protected synchronized JsonResult saveInsert(RequestSPage requestSPage, long hostId, long siteId) throws IOException {
        SPage sPage = requestSPage.makeSPage();
        sPage.setHostId(hostId).setSiteId(siteId);

        Long id = sPage.getId();

        if (id != null) {
            return JsonResult.illegal();
        }

        Short type = sPage.getType();
        Long systemId = sPage.getSystemId();
        Long parentId = sPage.getParentId();
        String name = sPage.getName();
        String rewrite = sPage.getRewrite();
        String target = sPage.getTarget();
        String url = sPage.getUrl();

        // 新增页面
        if (type == null || systemId == null || parentId == null) {
            return JsonResult.illegal();
        }

        if (StrUtil.isBlank(name) || StrUtil.isBlank(target)) {
            return JsonResult.illegal();
        }

        // 非外链页面，rewrite不能为空
        if (type.shortValue() != (short) 3 && StrUtil.isBlank(rewrite)) {
            return JsonResult.illegal();
        }

        // 验证父级是否存在
        if (parentId.longValue() < 1) {
            parentId = 0L;
        } else {
            SPage parentSPage = getInfoById(parentId, hostId, siteId);
            if (parentSPage == null) {
                return JsonResult.illegal();
            }
        }

        if (type.shortValue() == (short) 0) {
            // 引导页
        } else if (type.shortValue() == (short) 1) {
            // 普通页
            if (systemId.longValue() != 0) {
                return JsonResult.illegal();
            }
        } else if (type.shortValue() == (short) 2) {
            // 系统页
            if (systemId.longValue() < 1) {
                return JsonResult.illegal();
            }
            // 验证系统是否存在
            SSystem sSystem = systemServiceImpl.getInfoById(systemId, hostId, siteId);
            if (sSystem == null) {
                return JsonResult.illegal();
            }
        } else if (type.shortValue() == (short) 3) {
            // 外链页
            if (StrUtil.isBlank(url)) {
                return JsonResult.illegal();
            }
            sPage.setRewrite("");
        } else if (type.shortValue() == (short) 4) {
            // 内链页
        }

        // 非外链页面，需要对 rewrite 进行校验
        if (type.shortValue() != (short) 3) {
            // 自定义链接 是否包含特殊字符
            String pattern = "([\u4e00-\u9fa5]|[a-zA-Z0-9])+";
            if (!Pattern.matches(pattern, rewrite)) {
                return JsonResult.messageError("非全部数字或带空格特殊符号！");
            }
            // 自定义链接系统中是否存在
            List<Map<String, String>> defaultRewrite = CurrentSiteSPageRewriteExistValid.defaultRewrite;
            for (Map<String, String> ptn : defaultRewrite) {
                if (CurrentSiteSPageRewriteExistValid.isMatch(ptn.get("pattern"), rewrite)) {
                    return JsonResult.messageError("自定义链接在系统中已存在！");
                }
            }
            if (!validRewrite(sPage)) {
                return JsonResult.messageError("自定义链接系统中已存在");
            }
        }

        // 验证是否能够插入数据
        int page = hostSetupServiceImpl.getPage();
        int usedPage = hostSetupServiceImpl.getUsedPage();
        if ((usedPage + 1) > page) {
            return JsonResult.messageError("页面数量上限，无法正常添加！");
        }

        // 写入数据
        SPage insert = null;
        try {
            insert = insertSPageAppendOrderNum(sPage);
        } catch (HostSetuptException e) {
            e.printStackTrace();
        }

        if (insert == null) {
            return JsonResult.assistance();
        }

        webSiteServiceImpl.cacheCurrentSiteClear();

        return JsonResult.messageSuccess(insert);
    }

    @Override
    public JsonResult copy(RequestSPageCopy sPageCopy) throws IOException {
        long copyPageId = sPageCopy.getCopyPageId();
        long toSiteId = sPageCopy.getToSiteId();
        String name = StrUtil.trim(sPageCopy.getName());
        String rewrite = sPageCopy.getRewrite();
        String url = sPageCopy.getUrl();
        long afterPageId = sPageCopy.getAfterPageId();

        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();

        if (toSiteId < 0) {
            toSiteId = siteId;
        } else {
            List<Site> sites = requestHolder.getSites();
            AtomicLong toSiteIdAtomic = new AtomicLong(toSiteId);
            Optional<Site> findFirst = sites.stream().filter(item -> {
                return item.getId().longValue() == toSiteIdAtomic.get();
            }).findFirst();
            if (!findFirst.isPresent()) {
                return JsonResult.illegal();
            }
        }

        if (StrUtil.isBlank(name)) {
            return JsonResult.illegal();
        }

        RestResult restResult = sPageFeign.findByIdHostSiteId(copyPageId, hostId, siteId);
        SPage copySPage = RestResultUtil.data(restResult, SPage.class);
        if (copySPage == null) {
            return JsonResult.illegal();
        }

        // 普通页面或系统页面时 rewrite 不能为空且不能已经存在于系统中
        Short type = copySPage.getType();
        if (type == null) {
            return JsonResult.assistance();
        }
        // 非外链页面，需要对 rewrite 进行校验
        if (type.shortValue() != (short) 3) {
            if (StrUtil.isBlank(rewrite)) {
                return JsonResult.illegal();
            }
            // 自定义链接 是否包含特殊字符
            String pattern = "([\u4e00-\u9fa5]|[a-zA-Z0-9])+";
            if (!Pattern.matches(pattern, rewrite)) {
                return JsonResult.messageError("非全部数字或带空格特殊符号！");
            }
            // 自定义链接系统中是否存在
            List<Map<String, String>> defaultRewrite = CurrentSiteSPageRewriteExistValid.defaultRewrite;
            for (Map<String, String> ptn : defaultRewrite) {
                if (CurrentSiteSPageRewriteExistValid.isMatch(ptn.get("pattern"), rewrite)) {
                    return JsonResult.messageError("自定义链接在系统中已存在！");
                }
            }
            if (!validRewrite(null, rewrite)) {
                return JsonResult.messageError("自定义链接系统中已存在");
            }
        } else {
            if (StrUtil.isBlank(url)) {
                url = copySPage.getUrl();
            }
        }

        SPage afterSPage = null;
        if (afterPageId > 0) {
            restResult = sPageFeign.findByIdHostSiteId(afterPageId, hostId, siteId);
            afterSPage = RestResultUtil.data(restResult, SPage.class);
            if (afterSPage == null) {
                return JsonResult.illegal();
            }
        }

        // 验证是否能够插入数据
        int page = hostSetupServiceImpl.getPage();
        int usedPage = hostSetupServiceImpl.getUsedPage();
        if ((usedPage + 1) > page) {
            return JsonResult.messageError("页面数量上限，无法正常添加！");
        }

        // copy 动作执行
        FeignCopyPage feignCopyPage = new FeignCopyPage();
        feignCopyPage.setCopySPage(copySPage).setToSiteId(toSiteId).setName(name).setRewrite(rewrite).setUrl(url).setAfterSPage(afterSPage);

        restResult = cCopyFeign.page(feignCopyPage);
        SPage data = RestResultUtil.data(restResult, SPage.class);
        if (data == null) {
            return JsonResult.assistance();
        }
        return JsonResult.ok(data);
    }

}
